.text
.code16 // Assembly generates 16 bit machine instructions
.start16:
 cli // Clear the interrupt bit in the flag register, informing the processor not to respond to interrupts until 64 bit mode
 
 lgdt gdtr // Notify processor of segment descriptor table address

 mov %cr0, %eax // Set the 0th bit PE of the CR0 register to 1 and enable protection mode
 or $0x1, %eax
 mov %eax, %cr0
 
 ljmpl $0x8, $0x20000 // Jump to the 32-bit protected mode code segment section
 
gdt: // Definition of segment descriptor table
 .quad 0x0000000000000000 // 0st descriptor - No need, x86 convention is 0
 .quad 0x00c09a00000007ff // 1st descriptor - kernel code segment
 .quad 0x00c09200000007ff // 2nd descriptor - kernel data segment
gdt_end:

gdtr: // Segment descriptor table address definition, total of 6 bytes
 .word gdt_end - gdt // Low 16 bits - Table length - Starting and ending offset difference of 2 bytes
 .word gdt, 0x1 // High 32-bit - Table Address 2 2-Bytes